﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include <QFile>
#include <QApplication>

// custom headers
#include "EditingProjectComponentContext.h"
#include "PathUtils.h"
#include "CustomReply.h"
#include "CustomFileReply.h"
#include "ProjectCloudComponentService.h"
#include "ProjectLocalComponentService.h"
#include "IEditingProjectComponent.h"
#include "IDetailedProjectComponent.h"
#include "ISpecification.h"
#include "IParameter.gcs.h"
#include "IParameterDefinition.h"
#include "PropertyService.h"
#include "IPagedData.h"
#include "ICategoryProperty.h"
#include "PropertyService.h"
#include "FamilyFileService.h"
#include "IProjectComponent.h"
#include "IGmepGcsCategory.h"
#include "AppService.h"

#include "json/reader.h"
#include <QJsonArray>
#include "ComponentCommonUtils.h"

#include "UniIdentity.h"
#include "GbmpGuid.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 

namespace gmepgcs
{
    EditingProjectComponentContext::EditingProjectComponentContext(
        const std::wstring &projectId,
        const std::wstring &enterpriseId,
        const std::wstring &componentId,
        const int32_t &componentVersion,
        const std::wstring &componentName,
        QObject *parent) : 
        QObject(parent),
        m_projectId(projectId),
        m_enterpriseId(enterpriseId),
        m_componentId(componentId),
        m_componentVersion(componentVersion),
        m_originalComponentName(componentName)
    {
        Init();
    }

    EditingProjectComponentContext::~EditingProjectComponentContext()
    {
    }
    

    std::wstring EditingProjectComponentContext::GetComponentLocalFilePath() const
    {
        return m_componentLocalFilePath;
    }
    
    std::wstring EditingProjectComponentContext::GetLegendThumbnailLoalFilePath(const std::wstring & legendId) const
    {
        auto foundIterator = m_mpLegendThumbnailLocalFilePaths.find(legendId);
        if (foundIterator != m_mpLegendThumbnailLocalFilePaths.end())
        {
            return foundIterator->second;
        }

        return std::wstring();
    }
    
    bool EditingProjectComponentContext::Stage(const std::wstring &spec, bool bNeedUpdate)
    {
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
        auto allSuccess = 
            UpdateDrivenParameters(spec, std::wstring(), bNeedUpdate)  &&
            UpdateGeometry(spec, std::wstring(), bNeedUpdate);

        if (allSuccess)
        {
            m_lastStageFailed = false;
            if (m_spActiveComponent != nullptr)
                m_spStagedComponent = m_spActiveComponent->Clone();
            else
                m_spStagedComponent = nullptr;
        }
        else
        {
            m_lastStageFailed = true;
        }

        CheckModifyState();

        QApplication::restoreOverrideCursor();
        emit StageFinished(allSuccess);

        return allSuccess;
    }

    // 保存按钮后， 若有重新加载族， 则返回nNum， 若用户check 同步至项目构件库，syncInfo 返回同步的信息， 如：1个构件上传修改成功/ 后台正在解析等。
    bool EditingProjectComponentContext::Save(const bool &willUpdateComponentAfter,int& nNum, bool& hasChangeAfterSync, std::wstring& syncInfo)
    {
        if (!m_spActiveComponent)
        {
            emit SaveFinished(false, QString::fromStdWString(GBMP_TR(L"保存内容为空")).toStdWString(), nullptr, false);
            return false;
        }

        if (m_state & ModifyState::Dirty) // 若有更改， 更新预览， 保证被驱动参数也被更新
        {
            auto result = Stage(m_currentSpecificationName, false);
            if (!result)
            {
                emit SaveFinished(false, QString::fromStdWString(GBMP_TR(L"构件服务更新失败")).toStdWString(), nullptr, false);
                return false;
            }
        }

         //先做本地保存
        int iNewVersion = m_spActiveComponent->Version;
        {
            std::wstring strError = L"";
            if (!ProjectLocalComponentService::Get()->SaveModifiedComponent(m_projectId, *(m_spActiveComponent), iNewVersion, strError)) // 本地保存到db3
            {
                emit SaveFinished(false, strError, nullptr, false);
                return false;
            }
            else 
            {
                // 若原构件无修改，dirtyFlag 为0， 则新version 为m_spActiveComponent->Version+1， 若原构件已经有本地修改，则新version 为m_spActiveComponent->Version
                // 强制更新到工作单元的实例
                std::vector<std::tuple<std::wstring, int, bool>> updateComponentInDocument;
                updateComponentInDocument.emplace_back(std::make_tuple(m_spActiveComponent->Id, iNewVersion, iNewVersion == m_spActiveComponent->Version));
                nNum = ProjectLocalComponentService::Get()->UpdateFamiliesInDocument(updateComponentInDocument);
            }
        }
        // 若用户点击了同步至协同项目构件库， 则后做上传和merge， 可能包含再次强制更新到工作单元的实例
        if (willUpdateComponentAfter) 
        {
            std::vector<IProjectComponent> compVec;
            IProjectComponent projComp;
            projComp.Id = m_spActiveComponent->Id;
            projComp.Version = iNewVersion;
            projComp.Name = m_spActiveComponent->Name;
            projComp.PublicComponentId = m_spActiveComponent->PublicComponentId;
            projComp.CategoryCode = m_spActiveComponent->CategoryCode;

            compVec.push_back(projComp);
            hasChangeAfterSync = ProjectLocalComponentService::Get()->SyncComponents(m_projectId, m_enterpriseId, compVec, syncInfo);
        }
        return true;
    }

    QString EditingProjectComponentContext::GetActiveComponentName() const
    {
        if (!m_spActiveComponent)
        {
            return QString();
        }

        auto name = QString::fromStdWString(m_spActiveComponent->Name);
        if (!m_componentNameExtension.isEmpty())
        {
            name = name.mid(0, name.length() - m_componentNameExtension.size());
        }

        return name;
    }
    
    std::wstring EditingProjectComponentContext::GetOriginalComponentName() const
    {
        if (!m_spOriginalComponent)
        {
            return std::wstring();
        }

        return m_spOriginalComponent->Name;
    }

    std::wstring EditingProjectComponentContext::GetActiveCategoryCode() const
    {
        DBG_WARN_AND_RETURN_UNLESS(m_spActiveComponent != nullptr, std::wstring(), L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
        return m_spActiveComponent->CategoryCode;
    }

    std::wstring EditingProjectComponentContext::GetActiveCategoryGuid() const
    {
        DBG_WARN_AND_RETURN_UNLESS(m_spActiveComponent != nullptr, std::wstring(), L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
        return m_spActiveComponent->CategoryGuid;
    }

    std::wstring EditingProjectComponentContext::GetActiveCategoryFullName() const
    {
        try
        {
            DBG_WARN_AND_RETURN_UNLESS(m_spActiveComponent != nullptr, std::wstring(), L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
            auto categories = GetFullCategories(m_spActiveComponent->CategoryCode);
            std::wstring fullName;
            for (auto &category : categories)
            {
                DBG_WARN_AND_CONTINUE_UNLESS(category != nullptr, L"category为空", L"GMEP", L"2024-01-30");
                fullName += category->Name;
                fullName += L">";
            }

            if (fullName.back() == L'>')
            {
                fullName.pop_back();
            }

            return fullName;
        }
        catch (const std::exception&)
        {
            return std::wstring();
        }
    }

    std::vector<std::wstring> EditingProjectComponentContext::GetActiveSpecifications()
    {
        if (!m_spActiveComponent)
        {
            return std::vector<std::wstring>();
        }

        std::vector<std::wstring> specs;
        for (auto &specPair : m_spActiveComponent->Specifications)
        {
            specs.push_back(specPair.first);
        }

        return specs;
    }

    std::wstring EditingProjectComponentContext::GetCurrentSpecificationName() const
    {
        return m_currentSpecificationName;
    }

    std::vector<std::shared_ptr<IParameter>> EditingProjectComponentContext::GetActiveGeometyParameters(const std::wstring &specificationName)
    {
        std::vector<std::shared_ptr<IParameter>> geometryParameters = 
            GetActiveParametersWithCondition(specificationName, [](std::shared_ptr<IParameter> spParam) {
            return spParam && spParam->IsVisible() && spParam->Definition && spParam->Definition->IsGeometry();});

        return geometryParameters;
        return std::vector<std::shared_ptr<IParameter>>();
    }

    std::vector<std::shared_ptr<IParameter>> EditingProjectComponentContext::GetActiveStandardParameters(const std::wstring &specificationName)
    {
        std::vector<std::shared_ptr<IParameter>> standardParameters =
            GetActiveParametersWithCondition(specificationName, [](std::shared_ptr<IParameter> spParam) {
            return spParam && spParam->IsVisible() && spParam->Definition && spParam->Definition->GetIsStandard();
        });

        return standardParameters;
        return std::vector<std::shared_ptr<IParameter>>();
    }

    std::vector<std::shared_ptr<IParameter>> EditingProjectComponentContext::GetActiveCustomParameters(const std::wstring &specificationName)
    {
        std::vector<std::shared_ptr<IParameter>> customParameters =
            GetActiveParametersWithCondition(specificationName, [](std::shared_ptr<IParameter> spParam) {
            return spParam && spParam->IsVisible() && spParam->Definition && !spParam->Definition->IsGeometry() && !spParam->Definition->GetIsStandard();
        });

        return customParameters;
        return std::vector<std::shared_ptr<IParameter>>();
    }

    std::map<std::wstring, std::shared_ptr<IParameterDefinition>> EditingProjectComponentContext::GetActiveParameterDefinitions()
    {
        std::map<std::wstring, std::shared_ptr<IParameterDefinition>> emptyMap;
        DBG_WARN_AND_RETURN_UNLESS(m_spActiveComponent != nullptr, emptyMap, L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
        return m_spActiveComponent->ParameterDefinitions;
    }

    std::shared_ptr<ICategoryProperty> EditingProjectComponentContext::GetActiveCategoryProperty()
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_spActiveComponent != nullptr, L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
        auto foundIterator = m_mpCategoryProperties.find(m_spActiveComponent->CategoryCode);
        if (foundIterator == m_mpCategoryProperties.end())
        {
            return std::shared_ptr<ICategoryProperty>();
        }

        return foundIterator->second;
    }

    std::vector<std::shared_ptr<IGmepGcsCategory>> EditingProjectComponentContext::GetCategories()
    {
        return m_vCategories;
    }

    std::shared_ptr<ILegend> EditingProjectComponentContext::GetActiveLegend(const ILegend::LegendType & legendType)
    {
        if (!m_spActiveComponent)
        {
            return std::shared_ptr<ILegend>();
        }

        auto foundLegendPairIterator = m_spActiveComponent->Legends.find(legendType);
        if (foundLegendPairIterator == m_spActiveComponent->Legends.end())
        {
            return std::shared_ptr<ILegend>();
        }

        return foundLegendPairIterator->second;
    }
       
    void EditingProjectComponentContext::Init()
    {
        if (m_originalComponentName.empty())
        {
            m_originalComponentName = QString::fromStdWString(L"%1.gac").arg(QString::fromStdWString(m_componentId)).toStdWString();
        }

        m_spOriginalComponent = std::make_shared<IEditingProjectComponent>();
        m_spDetailedProjectComponent = nullptr;
        m_vSpecifications = std::vector<std::shared_ptr<ISpecification>>();
        m_vLegends = std::vector<std::shared_ptr<ILegend>>();
        m_spPreparedCategoryProperty = nullptr;

        m_spActiveComponent = nullptr;
        m_spStagedComponent = nullptr;
        m_state = ModifyState::UnChanged | ModifyState::Clean | ModifyState::Valid;

        m_currentSpecificationName = std::wstring();

        m_isComponentDataReady = false; 
        m_isCategoryPropertyDataReady = false;
        m_isCategoriesDataReady = false;
        m_isSpecificationsDataReady = false;
        m_isLegendsDataReady = false;
        m_isComponentFileDataReady = false;

        m_mpCategoryProperties = std::map<std::wstring, std::shared_ptr<ICategoryProperty>>();

        m_vCategories = std::vector<std::shared_ptr<IGmepGcsCategory>>();

        m_customParametersBinByCategory = std::map<std::wstring, std::map<std::wstring, std::shared_ptr<ISpecification>>>();
        m_customParameterDefinitionsBinByCategory = std::map<std::wstring, std::map<std::wstring, std::shared_ptr<IParameterDefinition>>>();

        m_spFamilyFileService = nullptr;

        m_lastStageFailed = false;

        m_componentNameExtension = QString();
    }
    
    void EditingProjectComponentContext::Prepare()
    {
        PrepareDetailedComponent();
    }

    void EditingProjectComponentContext::PrepareDetailedComponent()
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(ProjectLocalComponentService::Get(), L"ProjectLocalComponentService::Get()为空", L"GMEP", L"2024-01-30");
        std::shared_ptr<IDetailedProjectComponent> pDetailedProjectComponent =
            ProjectLocalComponentService::Get()->GetDetailedComponent(
                m_projectId,
                m_componentId,
                m_componentVersion);

        if (!pDetailedProjectComponent)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取项目构件详情失败")).toStdWString());
            return;
        }

        /* connect(pDetailedProjectComponentReply, &CustomReply<std::shared_ptr<IDetailedProjectComponent>>::Finished, [=]() {
             if (!pDetailedProjectComponentReply->Error().empty())
             {
                 emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取项目构件详情失败").toStdWString());
                 pDetailedProjectComponentReply->deleteLater();
                 return;
             }

            std::shared_ptr<IDetailedProjectComponent> spDetailedComponent = pDetailedProjectComponentReply->Result();
            pDetailedProjectComponentReply->deleteLater();
            if (!pDetailedProjectComponent)
            {
                emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取项目构件详情失败").toStdWString());
                return;
            }*/
            
            m_spDetailedProjectComponent = pDetailedProjectComponent;

            SetIsComponentDataReay(true);
                                    
            PrepareCategoryProperty(m_spDetailedProjectComponent->CategoryCode);
        //});
    }

    void EditingProjectComponentContext::PrepareSpecifications()
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS( ProjectLocalComponentService::Get(), L" ProjectLocalComponentService::Get()为空", L"GMEP", L"2024-01-30");
        std::vector<std::shared_ptr<ISpecification>> pSpecifications =
            ProjectLocalComponentService::Get()->GetSpecifications(
                m_projectId,
                m_componentId,
                m_componentVersion);

        if ( pSpecifications.size() == 0)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取规格参数失败")).toStdWString());
            return;
        }
        
        /* connect(pSpecificationsReply, &CustomReply<std::vector<std::shared_ptr<ISpecification>>>::Finished, [=]() {
             if (!pSpecificationsReply->Error().empty())
             {
                 emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取规格参数失败").toStdWString());
                 pSpecificationsReply->deleteLater();
                 return;
             }*/
            
            m_vSpecifications = pSpecifications;
            SetIsSpecificationsDataReady(true);

            PrepareLegends();
        //});
    }
    
    void EditingProjectComponentContext::PrepareLegends()
    {
        if (m_spDetailedProjectComponent == nullptr)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取图例失败")).toStdWString());
            return;
        }

        std::vector<std::shared_ptr<ILegend>> pLegends =
            ProjectLocalComponentService::Get()->GetLegends(m_spDetailedProjectComponent.get());

        /*if (pLegends.size() == 0)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取图例失败")).toStdWString());
            return;
        }*/

        /*  connect(pLegendsReply, &CustomReply<std::vector<std::shared_ptr<ILegend>>>::Finished, [=]() {
              if (!pLegendsReply->Error().empty())
              {
                  emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取图例失败").toStdWString());
                  pLegendsReply->deleteLater();
                  return;
              }*/
            
            m_vLegends = pLegends;
            //pLegendsReply->deleteLater();
            SetIsLegendsDataReady(true);

            PrepareComponentFile();
        //});
    }

    void EditingProjectComponentContext::PrepareComponentFile()
    {
        if(m_spDetailedProjectComponent != nullptr)
            m_componentLocalFilePath = m_spDetailedProjectComponent->familyFilePath;

        SetIsComponentFileDataReady(true);

        CheckIsAllReady();
       // 
        /* CustomReply<std::wstring> *pDownloadUrlReply =
             ProjectCloudComponentService::Get()->GetComponentDownloadUrl(
                 m_projectId,
                 m_componentId,
                 m_componentVersion
             );

         if (!pDownloadUrlReply)
         {
             emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件下载地址失败").toStdWString());
             return;
         }

         connect(pDownloadUrlReply, &CustomReply<std::wstring>::Finished, [=]() {
             if (!pDownloadUrlReply->Error().empty())
             {
                 emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件下载地址失败").toStdWString());
                 pDownloadUrlReply->deleteLater();
                 return;
             }

             std::wstring downloadUrl = pDownloadUrlReply->Result();
             pDownloadUrlReply->deleteLater();
             if (downloadUrl.empty())
             {
                 emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件下载地址失败").toStdWString());
                 return;
             }

             CustomFileReply *pComponentDownloadReply =
                 ProjectCloudComponentService::Get()->DownloadComponent(downloadUrl, m_componentLocalFilePath);

             if (!pComponentDownloadReply)
             {
                 emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件几何数据失败").toStdWString());
                 return;
             }

             connect(pComponentDownloadReply, &CustomFileReply::Finished, [=]() {
                 if (!pComponentDownloadReply->Error().empty())
                 {
                     emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件几何数据失败").toStdWString());
                     pComponentDownloadReply->deleteLater();
                     return;
                 }

                 pComponentDownloadReply->deleteLater();

                 SetIsComponentFileDataReady(true);

                 CheckIsAllReady();
             });
         });    */
    }

    bool EditingProjectComponentContext::MountStandardParametersIntoComponent()
    {
        try
        {
            if (!m_spActiveComponent)
            {
                return false;
            }

            /*auto backupComponent = m_spActiveComponent->Clone();
            if (!backupComponent)
            {
                return false;
            }*/
            
            // standard parameter definitions to be removed
            auto oldEssentialStandardParameterDefinitionsToBeRemoved = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto oldExtendedStandardParameterDefinitionsToRemoved = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto oldNotStandardParameterDefinitionsToBeLeft = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            for (auto &paramDefPair : m_spActiveComponent->ParameterDefinitions)
            {
                auto paramDef = paramDefPair.second;
                if (paramDef)
                {
                    if (paramDef->GetIsStandard() && paramDef->GetIsEssential())
                    {
                        oldEssentialStandardParameterDefinitionsToBeRemoved[paramDef->GetName()] = paramDef;
                    }
                    else if (paramDef->GetIsStandard() && !paramDef->GetIsEssential())
                    {
                        oldExtendedStandardParameterDefinitionsToRemoved[paramDef->GetName()] = paramDef;
                    }
                    else
                    {
                        oldNotStandardParameterDefinitionsToBeLeft[paramDef->GetName()] = paramDef;
                    }
                }
            }

            // standard parameter definitions to be added
            auto newEssentialStandardParameterDefinitionsToBeAdded = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto newExtendedStandardParameterDefinitionsToBeAdded = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto foundCategorPropertyPair = m_mpCategoryProperties.find(m_spActiveComponent->CategoryCode);
            auto oldCustomParameterDefinitionsNewlyToBeSuppressed = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            if (foundCategorPropertyPair != m_mpCategoryProperties.end())
            {
                auto categoryProperty = foundCategorPropertyPair->second;
                if (categoryProperty)
                {
                    for (auto &paramDefPair : categoryProperty->Properties)
                    {
                        auto paramDef = paramDefPair.second;
                        if (paramDef && (paramDef->GetIsStandard()))
                        {
                            if (paramDef->GetIsEssential())
                            {
                                auto foundConflictParamDefIterator = oldNotStandardParameterDefinitionsToBeLeft.find(paramDef->GetName());
                                if (foundConflictParamDefIterator == oldNotStandardParameterDefinitionsToBeLeft.end())
                                {
                                    newEssentialStandardParameterDefinitionsToBeAdded[paramDef->GetName()] = paramDef;
                                }
                                else
                                {
                                    auto conflictParamDef = foundConflictParamDefIterator->second;
                                    if (conflictParamDef)
                                    {
                                        if (conflictParamDef->GetIsBuiltIn() || conflictParamDef->IsGeometry() || conflictParamDef->GetIsDrivingParameter() || conflictParamDef->GetIsOutputParameter())
                                        {
                                            continue;
                                        }
                                        else
                                        {
                                            newEssentialStandardParameterDefinitionsToBeAdded[paramDef->GetName()] = paramDef;
                                            oldCustomParameterDefinitionsNewlyToBeSuppressed[paramDef->GetName()] = conflictParamDef;
                                            oldNotStandardParameterDefinitionsToBeLeft.erase(paramDef->GetName());
                                        }
                                    }
                                }
                            }
                            else
                            {
                                auto foundIterator = std::find_if(
                                    oldExtendedStandardParameterDefinitionsToRemoved.begin(),
                                    oldExtendedStandardParameterDefinitionsToRemoved.end(),
                                    [paramDef](const std::map<std::wstring, std::shared_ptr<IParameterDefinition>>::value_type pair) {
                                    return (pair.second) && (pair.second->GetCode() == paramDef->GetCode());
                                });
                                if (foundIterator != oldExtendedStandardParameterDefinitionsToRemoved.end())
                                {
                                    auto foundConflictParamDefIterator = oldNotStandardParameterDefinitionsToBeLeft.find(paramDef->GetName());
                                    if (foundConflictParamDefIterator == oldNotStandardParameterDefinitionsToBeLeft.end())
                                    {
                                        newExtendedStandardParameterDefinitionsToBeAdded[paramDef->GetName()] = paramDef;
                                    }
                                    else
                                    {
                                        auto conflictParamDef = foundConflictParamDefIterator->second;
                                        if (conflictParamDef)
                                        {
                                            if (conflictParamDef->GetIsBuiltIn() || conflictParamDef->IsGeometry() || conflictParamDef->GetIsDrivingParameter() || conflictParamDef->GetIsOutputParameter())
                                            {
                                                continue;
                                            }
                                            else
                                            {
                                                newExtendedStandardParameterDefinitionsToBeAdded[paramDef->GetName()] = paramDef;
                                                oldCustomParameterDefinitionsNewlyToBeSuppressed[paramDef->GetName()] = conflictParamDef;
                                                oldNotStandardParameterDefinitionsToBeLeft.erase(paramDef->GetName());
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    auto foundConflictParamDefIterator = oldNotStandardParameterDefinitionsToBeLeft.find(paramDef->GetName());
                                    if (foundConflictParamDefIterator == oldNotStandardParameterDefinitionsToBeLeft.end())
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        auto conflictParamDef = foundConflictParamDefIterator->second;
                                        if (conflictParamDef)
                                        {
                                            if (conflictParamDef->GetIsBuiltIn() || conflictParamDef->IsGeometry() || conflictParamDef->GetIsDrivingParameter() || conflictParamDef->GetIsOutputParameter())
                                            {
                                                continue;
                                            }
                                            else
                                            {
                                                oldCustomParameterDefinitionsNewlyToBeSuppressed[paramDef->GetName()] = conflictParamDef;
                                                oldNotStandardParameterDefinitionsToBeLeft.erase(paramDef->GetName());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // custom parameter definitions to be desuppressed
            auto oldCustomParameterDefinitionsToBeDesuppressed = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto oldCustomParameterDefinitionsStillToBeSuppressed = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            auto foundCustomParameterDefinitionsBinIterator = m_customParameterDefinitionsBinByCategory.find(m_spActiveComponent->CategoryCode);
            if (foundCustomParameterDefinitionsBinIterator == m_customParameterDefinitionsBinByCategory.end())
            {
                m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            }
            
            for (auto &paramDefPair : m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode])
            {
                auto paramDef = paramDefPair.second;
                if (paramDef)
                {
                    auto fonudConflictParamDefIterator = oldNotStandardParameterDefinitionsToBeLeft.find(paramDef->GetName());
                    if (fonudConflictParamDefIterator != oldNotStandardParameterDefinitionsToBeLeft.end())
                    {
                        oldCustomParameterDefinitionsStillToBeSuppressed[paramDef->GetName()] = paramDef;
                        continue;
                    }

                    fonudConflictParamDefIterator = newEssentialStandardParameterDefinitionsToBeAdded.find(paramDef->GetName());
                    if (fonudConflictParamDefIterator != newEssentialStandardParameterDefinitionsToBeAdded.end())
                    {
                        oldCustomParameterDefinitionsStillToBeSuppressed[paramDef->GetName()] = paramDef;
                        continue;
                    }

                    fonudConflictParamDefIterator = newExtendedStandardParameterDefinitionsToBeAdded.find(paramDef->GetName());
                    if (fonudConflictParamDefIterator != newExtendedStandardParameterDefinitionsToBeAdded.end())
                    {
                        oldCustomParameterDefinitionsStillToBeSuppressed[paramDef->GetName()] = paramDef;
                        continue;
                    }

                    oldCustomParameterDefinitionsToBeDesuppressed[paramDef->GetName()] = paramDef;
                }
            }

            // update depressed definitions bin of active category
            for (auto desuppressedPair : oldCustomParameterDefinitionsToBeDesuppressed)
            {
                auto desuppressed = desuppressedPair.second;
                if (desuppressed)
                {
                    m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode].erase(desuppressed->GetName());
                }
            }

            if (oldCustomParameterDefinitionsNewlyToBeSuppressed.size() > 0)
            {
                m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
                m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode].insert(oldCustomParameterDefinitionsNewlyToBeSuppressed.begin(), oldCustomParameterDefinitionsNewlyToBeSuppressed.end()); // 遇到key相同时不会插入
            }

            // update active parameter definitions
            auto finalParameterDefinitions = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
            finalParameterDefinitions.insert(oldNotStandardParameterDefinitionsToBeLeft.begin(), oldNotStandardParameterDefinitionsToBeLeft.end());
            finalParameterDefinitions.insert(newEssentialStandardParameterDefinitionsToBeAdded.begin(), newEssentialStandardParameterDefinitionsToBeAdded.end());
            finalParameterDefinitions.insert(newExtendedStandardParameterDefinitionsToBeAdded.begin(), newExtendedStandardParameterDefinitionsToBeAdded.end());
            finalParameterDefinitions.insert(oldCustomParameterDefinitionsToBeDesuppressed.begin(), oldCustomParameterDefinitionsToBeDesuppressed.end());
            DBG_WARN_AND_RETURN_FALSE_UNLESS(m_spActiveComponent, L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
            m_spActiveComponent->ParameterDefinitions = finalParameterDefinitions;

            for (auto &specPair : m_spActiveComponent->Specifications)
            {
                auto &spec = specPair.second;
                if (spec)
                {
                    // update active specifications
                    std::map<std::wstring, std::shared_ptr<IParameter>> newParameters;                    

                    for (auto &oldToBeLeftParamDefPair : oldNotStandardParameterDefinitionsToBeLeft)
                    {
                        auto oldToBeLeftParamDef = oldToBeLeftParamDefPair.second;
                        if (oldToBeLeftParamDef)
                        {
                            std::shared_ptr<IParameter> newParameter = std::make_shared<IParameter>();
                            if (newParameter == nullptr)
                            {
                                continue;
                            }
                            newParameter->Definition = oldToBeLeftParamDef;

                            auto foundOldParamPair = spec->Parameters.find(oldToBeLeftParamDef->GetName());
                            if ((foundOldParamPair != spec->Parameters.end()) && (nullptr != foundOldParamPair->second))
                            {
                                newParameter->SetValue(foundOldParamPair->second->Value);
                            }

                            newParameters[newParameter->Definition->GetName()] = newParameter;
                        }
                    }

                    for (auto &newEssentialToBeAddedParamDefPair : newEssentialStandardParameterDefinitionsToBeAdded)
                    {
                        auto newEssentialToBeAddedParamDef = newEssentialToBeAddedParamDefPair.second;
                        if (newEssentialToBeAddedParamDef)
                        {
                            std::shared_ptr<IParameter> newParameter = std::make_shared<IParameter>();
                            if (newParameter = nullptr)
                            {
                                continue;
                            }
                            newParameter->Definition = newEssentialToBeAddedParamDef;

                            auto foundOldParamPair = std::find_if(spec->Parameters.begin(), spec->Parameters.end(), [newEssentialToBeAddedParamDef](const std::map<std::wstring, std::shared_ptr<IParameter>>::value_type item) {
                                return (item.second != nullptr) && (item.second->Definition != nullptr) && (item.second->Definition->GetCode() == newEssentialToBeAddedParamDef->GetCode());
                            });
                            if ((foundOldParamPair != spec->Parameters.end()) && (nullptr != foundOldParamPair->second))
                            {
                                newParameter->SetValue(foundOldParamPair->second->Value);
                            }

                            newParameters[newParameter->Definition->GetName()] = newParameter;
                        }
                    }

                    for (auto &newExtendedToBeAddedParamDefPair : newExtendedStandardParameterDefinitionsToBeAdded)
                    {
                        auto newExtendedToBeAddedParamDef = newExtendedToBeAddedParamDefPair.second;
                        if (newExtendedToBeAddedParamDef)
                        {
                            std::shared_ptr<IParameter> newParameter = std::make_shared<IParameter>();
                            if (newParameter == nullptr)
                            {
                                continue;
                            }
                            newParameter->Definition = newExtendedToBeAddedParamDef;

                            auto foundOldParamPair = std::find_if(spec->Parameters.begin(), spec->Parameters.end(), [newExtendedToBeAddedParamDef](const std::map<std::wstring, std::shared_ptr<IParameter>>::value_type item) {
                                return (item.second != nullptr) && (item.second->Definition != nullptr) && (item.second->Definition->GetCode() == newExtendedToBeAddedParamDef->GetCode());
                            });
                            if ((foundOldParamPair != spec->Parameters.end()) && (nullptr != foundOldParamPair->second))
                            {
                                newParameter->SetValue(foundOldParamPair->second->Value);
                            }

                            newParameters[newParameter->Definition->GetName()] = newParameter;
                        }
                    }

                    for (auto &oldDesuppressedParamDefPair : oldCustomParameterDefinitionsToBeDesuppressed)
                    {
                        auto oldDesuppressedParamDef = oldDesuppressedParamDefPair.second;
                        if (oldDesuppressedParamDef)
                        {
                            std::shared_ptr<IParameter> newParameter = std::make_shared<IParameter>();
                            DBG_WARN_AND_CONTINUE_UNLESS(newParameter != nullptr, L"newParameter为空", L"GMEP", L"2024-01-30");
                            newParameter->Definition = oldDesuppressedParamDef;

                            auto foundParametersBinByCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
                            if (foundParametersBinByCategoryIterator != m_customParametersBinByCategory.end())
                            {
                                auto foundSuppressedSpecIterator = foundParametersBinByCategoryIterator->second.find(spec->Name);
                                if (foundSuppressedSpecIterator != foundParametersBinByCategoryIterator->second.end())
                                {
                                    auto foundSuppressedSpec = foundSuppressedSpecIterator->second;
                                    if (foundSuppressedSpec)
                                    {
                                        auto foundSuppressedParameterIterator = foundSuppressedSpec->Parameters.find(oldDesuppressedParamDef->GetName());
                                        if (foundSuppressedParameterIterator != foundSuppressedSpec->Parameters.end())
                                        {
                                            auto foundSuppressedParameter = foundSuppressedParameterIterator->second;
                                            if (foundSuppressedParameter)
                                            {
                                                newParameter->SetValue(foundSuppressedParameter->Value);
                                            }
                                        }
                                    }
                                }
                            }

                            newParameters[newParameter->Definition->GetName()] = newParameter;
                        }
                    }
                    
                    // update suppressed parameters of the spec under the category
                    auto foundParametersBinByCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
                    if (foundParametersBinByCategoryIterator == m_customParametersBinByCategory.end())
                    {
                        m_customParametersBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<ISpecification>>();
                    }

                    auto foundSuppressedSpecIterator = m_customParametersBinByCategory[m_spActiveComponent->CategoryCode].find(spec->Name);
                    if (foundSuppressedSpecIterator == m_customParametersBinByCategory[m_spActiveComponent->CategoryCode].end())
                    {
                        m_customParametersBinByCategory[m_spActiveComponent->CategoryCode][spec->Name] = std::make_shared<ISpecification>();
                        DBG_WARN_AND_CONTINUE_UNLESS(m_customParametersBinByCategory[m_spActiveComponent->CategoryCode][spec->Name] != nullptr,
                            L"m_customParametersBinByCategory[m_spActiveComponent->CategoryCode][spec->Name]为空", L"GMEP", L"2024-01-30");
                        m_customParametersBinByCategory[m_spActiveComponent->CategoryCode][spec->Name]->Name = spec->Name;
                    }

                    auto &suppressedSpec = m_customParametersBinByCategory[m_spActiveComponent->CategoryCode][spec->Name];

                    std::map<std::wstring, std::shared_ptr<IParameter>> newSuppressedParameters;

                    auto &suppressedDefinitions = m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode];
                    for (auto &stillTobeSuppressedParamDefPair : oldCustomParameterDefinitionsStillToBeSuppressed)
                    {
                        auto stillToBeSuppressedParamDef = stillTobeSuppressedParamDefPair.second;
                        if (stillToBeSuppressedParamDef)
                        {
                            auto foundParamDefPairInDefinitionsIterator = suppressedDefinitions.find(stillToBeSuppressedParamDef->GetName());
                            if (foundParamDefPairInDefinitionsIterator != suppressedDefinitions.end())
                            {
                                auto foundParamDefinition = foundParamDefPairInDefinitionsIterator->second;
                                if (foundParamDefinition)
                                {
                                    std::shared_ptr<IParameter> newSuppressedParameter = std::make_shared<IParameter>();
                                    DBG_WARN_AND_CONTINUE_UNLESS(newSuppressedParameter != nullptr, L"newSuppressedParameter为空", L"GMEP", L"2024-01-30");
                                    newSuppressedParameter->Definition = foundParamDefinition;
                                    DBG_WARN_AND_CONTINUE_UNLESS(newSuppressedParameter->Definition != nullptr, L"newSuppressedParameter->Definition为空", L"GMEP", L"2024-01-30");

                                    auto foundParamIterator = suppressedSpec->Parameters.find(newSuppressedParameter->Definition->GetName());
                                    if (foundParamIterator != suppressedSpec->Parameters.end())
                                    {
                                        auto foundParam = foundParamIterator->second;
                                        if (foundParam)
                                        {
                                            newSuppressedParameter->SetValue(foundParam->Value);
                                        }
                                    }

                                    newSuppressedParameters[newSuppressedParameter->Definition->GetName()] = newSuppressedParameter;
                                }
                            }
                        }
                    }

                    for (auto &newlyToBeSuppressedParamDefPair : oldCustomParameterDefinitionsNewlyToBeSuppressed)
                    {
                        auto newlyToBeSuppressedParamDef = newlyToBeSuppressedParamDefPair.second;
                        if (newlyToBeSuppressedParamDef)
                        {
                            auto foundParamDefPairInDefinitionsIterator = suppressedDefinitions.find(newlyToBeSuppressedParamDef->GetName());
                            if (foundParamDefPairInDefinitionsIterator != suppressedDefinitions.end())
                            {
                                auto foundParamDefinition = foundParamDefPairInDefinitionsIterator->second;
                                if (foundParamDefinition)
                                {
                                    std::shared_ptr<IParameter> newSuppressedParameter = std::make_shared<IParameter>();
                                    DBG_WARN_AND_CONTINUE_UNLESS(newSuppressedParameter != nullptr, L"newSuppressedParameter为空", L"GMEP", L"2024-01-30");
                                    newSuppressedParameter->Definition = foundParamDefinition;

                                    auto foundParamIterator = spec->Parameters.find(newSuppressedParameter->Definition->GetName());
                                    if (foundParamIterator != spec->Parameters.end())
                                    {
                                        auto foundParam = foundParamIterator->second;
                                        if (foundParam)
                                        {
                                            newSuppressedParameter->SetValue(foundParam->Value);
                                        }
                                    }

                                    newSuppressedParameters[newSuppressedParameter->Definition->GetName()] = newSuppressedParameter;
                                }
                            }
                        }
                    }

                    // finally set data
                    spec->Parameters = newParameters;
                    suppressedSpec->Parameters = newSuppressedParameters;
                }
            }

            CheckModifyState();

            return true;
        }
        catch (const std::exception&)
        {
            return false;
        }
    }

    void EditingProjectComponentContext::PrepareCategoryProperty(const std::wstring &categoryCode)
    {
        auto pPropertyService = PropertyService::Get();
        if (!pPropertyService)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"PropertyService为空")).toStdWString());
            return;
        }

        auto pAppService = AppService::Get();
        if (!pAppService)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"AppService为空")).toStdWString());
            return;
        }

        std::shared_ptr<ICategoryProperty> pCategoryProperty =
            pPropertyService->GetCategoryProperty(categoryCode);

        if (pCategoryProperty == nullptr)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取分类下的参数列表失败")).toStdWString());
            return;
        }

        // 确实存在某些分类下没有标准属性的情形，空指针仍接收，使用时做校验即可
        m_spPreparedCategoryProperty = pCategoryProperty;
        SetIsCategoryPropertyDataReady(true);

        PrepareCategories();
    }

    void EditingProjectComponentContext::PrepareCategories()
    {
        std::vector<std::shared_ptr<IGmepGcsCategory>> pCategories =
            PropertyService::Get()->GetCategories();

        if (pCategories.size() == 0)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取分类数据失败")).toStdWString());
            return;
        }

        m_vCategories = pCategories;
        SetIsCategoriesDataReady(true);

        PrepareSpecifications();
    }

    void EditingProjectComponentContext::SetIsComponentDataReay(const bool ready)
    {
        m_isComponentDataReady = ready; 
    }

    void EditingProjectComponentContext::SetIsCategoryPropertyDataReady(const bool ready)
    {
        m_isCategoryPropertyDataReady = ready;
    }

    void EditingProjectComponentContext::SetIsCategoriesDataReady(const bool ready)
    {
        m_isCategoriesDataReady = ready;
    }

    void EditingProjectComponentContext::SetIsSpecificationsDataReady(const bool ready)
    {
        m_isSpecificationsDataReady = ready;
    }
    
    void EditingProjectComponentContext::SetIsLegendsDataReady(const bool ready)
    {
        m_isLegendsDataReady = ready;
    }

    void EditingProjectComponentContext::SetIsComponentFileDataReady(const bool ready)
    {
        m_isComponentFileDataReady = ready; 
    }

    void EditingProjectComponentContext::CheckIsAllReady()
    {
        bool isAllReady =
            m_isComponentDataReady &&
            m_isCategoryPropertyDataReady &&
            m_isCategoriesDataReady &&
            m_isSpecificationsDataReady &&
            m_isLegendsDataReady &&
            m_isComponentFileDataReady;

        if (!isAllReady)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"准备数据失败")).toStdWString());
            return;
        }
        
        if (!m_spOriginalComponent)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件数据失败")).toStdWString());
            return;
        }

        if (!m_spDetailedProjectComponent)
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取项目构件详情失败")).toStdWString());
            return;
        }

        if (!QFile::exists(QString::fromStdWString(m_componentLocalFilePath)))
        {
            emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"获取构件几何数据失败")).toStdWString());
            return;
        }

        // populate m_spOriginalComponent at one time
        {
            m_spOriginalComponent->Id = m_spDetailedProjectComponent->Id;
            m_spOriginalComponent->PublicComponentId = m_spDetailedProjectComponent->PublicComponentId;
            m_spOriginalComponent->Version = m_spDetailedProjectComponent->Version;
            m_spOriginalComponent->Name = m_spDetailedProjectComponent->Name;
            m_spOriginalComponent->CategoryCode = m_spDetailedProjectComponent->CategoryCode;
            m_spOriginalComponent->CategoryGuid = m_spDetailedProjectComponent->CategoryId;
            m_spOriginalComponent->PublicSourceVersion = m_spDetailedProjectComponent->PublicSourceVersion;
            if (!(m_spDetailedProjectComponent->Name.empty()))
            {
                auto qName = QString::fromStdWString(m_spDetailedProjectComponent->Name);
                auto splits = qName.split(QChar('.'));
                auto count = splits.size();
                if (count > 1)
                {
                    auto suffix = splits[count - 1].trimmed();
                    if (QString::compare(suffix, "gac", Qt::CaseInsensitive) == 0)
                    {
                        m_componentNameExtension = QString::fromStdWString(L".%1").arg(suffix);
                    }
                }
            }

            for (auto specifation : m_vSpecifications)
            {
                if (!specifation)
                {
                    continue;
                }

                m_spOriginalComponent->Specifications[specifation->Name] = specifation;

                if (m_currentSpecificationName.empty())
                {
                    m_currentSpecificationName = specifation->Name;
                }

                if (m_spOriginalComponent->ParameterDefinitions.empty())
                {
                    for (auto &parameterPair : specifation->Parameters)
                    {
                        if (parameterPair.second && parameterPair.second->Definition)
                        {
                            m_spOriginalComponent->ParameterDefinitions[parameterPair.second->Definition->GetName()] = parameterPair.second->Definition;
                        }
                    }
                }
            }

            for (auto legend : m_vLegends)
            {
                if (legend)
                {
                    m_spOriginalComponent->Legends[legend->Type] = legend;
                }
            }

            m_mpCategoryProperties[m_spDetailedProjectComponent->CategoryCode] = m_spPreparedCategoryProperty;
        }

        m_spActiveComponent = m_spOriginalComponent->Clone();
         m_spStagedComponent = m_spOriginalComponent->Clone();
          if ((!m_spActiveComponent) || (!m_spStagedComponent))
         {
             emit PrepareFinished(false, QString::fromStdWString(GBMP_TR(L"克隆构件数据失败")).toStdWString());
             return;
         }

         emit PrepareFinished(true, std::wstring());
    }

    std::vector<std::shared_ptr<IParameter>> EditingProjectComponentContext::GetActiveParametersWithCondition(
        const std::wstring &specificationName, bool(* predicate)(std::shared_ptr<IParameter>))
    {
        std::vector<std::shared_ptr<IParameter>> parameters;

        if (m_spActiveComponent)
        {
            auto foundSpecIterator = m_spActiveComponent->Specifications.find(specificationName);
            if (foundSpecIterator != m_spActiveComponent->Specifications.end())
            {
                auto foundSpec = foundSpecIterator->second;
                if (foundSpec)
                {
                    for (auto &paramPair : foundSpec->Parameters)
                    {
                        auto param = paramPair.second;
                        if (predicate(param))
                        {
                            parameters.push_back(param);
                        }
                    }
                }
            }
        }

        return parameters;
    }

    void EditingProjectComponentContext::CheckModifyState()
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_spActiveComponent, L"m_spActiveComponent为空", L"GMEP", L"2024-01-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_spOriginalComponent, L"m_spOriginalComponent为空", L"GMEP", L"2024-01-30");
        bool changed = *(m_spActiveComponent) != *(m_spOriginalComponent);

        std::shared_ptr<ISpecification> compactStagedSpec = std::make_shared<ISpecification>();
        DBG_WARN_AND_RETURN_VOID_UNLESS(compactStagedSpec != nullptr, L"compactStagedSpec为空", L"GMEP", L"2024-01-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_spStagedComponent != nullptr, L"m_spStagedComponent为空", L"GMEP", L"2024-01-30");
        auto foundStagedSpecIterator = m_spStagedComponent->Specifications.find(m_currentSpecificationName);
        if (foundStagedSpecIterator != m_spStagedComponent->Specifications.end())
        {
            auto foundStagedSpec = foundStagedSpecIterator->second;
            if (foundStagedSpec)
            {
                compactStagedSpec->Name = foundStagedSpec->Name;
                for (auto &paramPair : foundStagedSpec->Parameters)
                {
                    auto param = paramPair.second;
                    if (param && param->Definition)
                    {
                        if (param->Definition->GetIsDrivingParameter() || param->Definition->IsGeometry())
                        {
                            compactStagedSpec->Parameters[param->Definition->GetName()] = param;
                        }
                    }
                }
            }
        }
        std::shared_ptr<ISpecification> compactActiveSpec = std::make_shared<ISpecification>();
        DBG_WARN_AND_RETURN_VOID_UNLESS(compactActiveSpec != nullptr, L"compactActiveSpec为空", L"GMEP", L"2024-01-30");
        auto foundActiveSpecIterator = m_spActiveComponent->Specifications.find(m_currentSpecificationName);
        if (foundActiveSpecIterator != m_spActiveComponent->Specifications.end())
        {
            auto foundActiveSpec = foundActiveSpecIterator->second;
            if (foundActiveSpec)
            {
                compactActiveSpec->Name = foundActiveSpec->Name;
                for (auto &paramPair : foundActiveSpec->Parameters)
                {
                    auto param = paramPair.second;
                    if (param && param->Definition)
                    {
                        if (param->Definition->GetIsDrivingParameter() || param->Definition->IsGeometry())
                        {
                            compactActiveSpec->Parameters[param->Definition->GetName()] = param;
                        }
                    }
                }
            }
        }
        bool dirty = (*(compactActiveSpec) != *(compactStagedSpec)) || (m_lastStageFailed);

        int newState = 0;
        newState |= changed ? ModifyState::Changed : ModifyState::UnChanged;
        newState |= dirty ? ModifyState::Dirty : ModifyState::Clean;
        newState |= CheckActiveValid() ? ModifyState::Valid : ModifyState::Invalid;

        if (newState != m_state)
        {
            int oldState = m_state;
            m_state = newState;
            emit StateChanged(oldState, newState);
        }
    }

    bool EditingProjectComponentContext::CheckActiveValid()
    {
        if (!m_spActiveComponent)
        {
            return false;
        }

        if (m_spActiveComponent->Name.empty())
        {
            return false;
        }
        // 非法字符 <>/\\\":?*| 认为不可以保存
        std::vector<std::wstring> cExceptChar{ L"<", L">", L"/", L"\\", L"\"",L":", L"?", L"*", L"|"};
        FOR_EACH(exceptChar, cExceptChar)
        {
            size_t iStart = m_spActiveComponent->Name.find(exceptChar);
            if (std::wstring::npos != iStart)
                return false;
        }
        return true;
    }


    void EditingProjectComponentContext::SwitchCurrentSpecificationTo(const std::wstring & targetSpecificationName)
    {
        if (m_currentSpecificationName == targetSpecificationName)
        {
            return;
        }

        if (!m_spActiveComponent)
        {
            return;
        }

        auto foundSpecIterator = m_spActiveComponent->Specifications.find(targetSpecificationName);
        if (foundSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return;
        }
        
        std::wstring oldCurrentSpec = m_currentSpecificationName;
        m_currentSpecificationName = targetSpecificationName;
        emit CurrentSpecificationChanged(oldCurrentSpec, m_currentSpecificationName);

        Stage(m_currentSpecificationName);
    }

    void EditingProjectComponentContext::ModifyComponentName(const std::wstring &componentName)
    {
        if (!m_spActiveComponent)
        {
            return;
        }

        auto name = componentName;
        if (!m_componentNameExtension.isEmpty())
        {
            name = name + m_componentNameExtension.toStdWString();
        }

        m_spActiveComponent->Name = name;

        CheckModifyState();
    }
    // 允许切换分类？
    void EditingProjectComponentContext::ModifyComponentCategory(const std::wstring & categoryCode)
    {
        if (m_spActiveComponent == nullptr || m_spActiveComponent->CategoryCode == categoryCode)
        {
            return;
        }

        if (categoryCode.empty())
        {
            emit ModifyComponentCategoryFinished(false, QString::fromStdWString(GBMP_TR(L"所选分类无效")).toStdWString());
            return;
        }

        auto foundCategoryPropertyIterator = m_mpCategoryProperties.find(categoryCode);
        if (foundCategoryPropertyIterator != m_mpCategoryProperties.end() && foundCategoryPropertyIterator->second)
        {
            m_spActiveComponent->CategoryCode = categoryCode;
            MountStandardParametersIntoComponent();

            emit ModifyComponentCategoryFinished(true, std::wstring());
            return;
        }

        std::shared_ptr<ICategoryProperty> pCategoryProperty =
            PropertyService::Get()->GetCategoryProperty(categoryCode);

        if (!pCategoryProperty)
        {
            emit ModifyComponentCategoryFinished(false, QString::fromStdWString(GBMP_TR(L"获取分类下的参数列表失败")).toStdWString());
            return;
        }

      

            std::shared_ptr<ICategoryProperty> spCategoryProperty = pCategoryProperty;
            m_mpCategoryProperties[categoryCode] = spCategoryProperty;

            m_spActiveComponent->CategoryCode = categoryCode;
            MountStandardParametersIntoComponent();

            emit ModifyComponentCategoryFinished(true, std::wstring());
            return;
    }

    void EditingProjectComponentContext::RemoveSpecification(const std::wstring & specificationName)
    {
        if (!m_spActiveComponent)
        {
            return;
        }

        if (m_spActiveComponent->Specifications.size() <= 1)
        {
            return;
        }

        auto foundSpecIterator = m_spActiveComponent->Specifications.find(specificationName);
        if (foundSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return;
        }

        m_spActiveComponent->Specifications.erase(specificationName);

        // erase the spec in suppressed bin
        auto foundParamBinOfCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundParamBinOfCategoryIterator != m_customParametersBinByCategory.end())
        {
            auto foundParamBinOfSpecIterator = foundParamBinOfCategoryIterator->second.find(specificationName);
            if (foundParamBinOfSpecIterator != foundParamBinOfCategoryIterator->second.end())
            {
                foundParamBinOfCategoryIterator->second.erase(specificationName);
            }
        }
        
        auto specs = GetActiveSpecifications();
        emit SpecificationItemsChanged(specs);

        SwitchCurrentSpecificationTo(*(specs.begin()));
        CheckModifyState();
    }

    void EditingProjectComponentContext::RenameSpecification(const std::wstring specificationOldName, const std::wstring specificationNewName)
    {
        if (!m_spActiveComponent)
        {
            return;
        }

        auto finalSpecificationNewName = QString::fromStdWString(specificationNewName).trimmed().toStdWString();
        if (finalSpecificationNewName.empty())
        {
            return;
        }

        if (specificationOldName == finalSpecificationNewName)
        {
            return;
        }

        auto foundOldSpecIterator = m_spActiveComponent->Specifications.find(specificationOldName);
        if (foundOldSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return;
        }

        auto foundNewSpecIterator = m_spActiveComponent->Specifications.find(finalSpecificationNewName);
        if (foundNewSpecIterator != m_spActiveComponent->Specifications.end())
        {
            return;
        }

        auto spec = m_spActiveComponent->Specifications[specificationOldName];
        if (spec == nullptr)
            return;
        spec->Name = finalSpecificationNewName;
        m_spActiveComponent->Specifications.erase(specificationOldName);
        m_spActiveComponent->Specifications[finalSpecificationNewName] = spec;

        // rename the spec in suppressed bin
        auto foundParamBinOfCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundParamBinOfCategoryIterator != m_customParametersBinByCategory.end())
        {
            auto foundParamBinOfSpecIterator = foundParamBinOfCategoryIterator->second.find(specificationOldName);
            if (foundParamBinOfSpecIterator != foundParamBinOfCategoryIterator->second.end())
            {
                auto suppressedOldSpec = foundParamBinOfCategoryIterator->second[specificationOldName];
                if (suppressedOldSpec)
                {
                    suppressedOldSpec->Name = finalSpecificationNewName;
                }
                foundParamBinOfCategoryIterator->second.erase(specificationOldName);
                foundParamBinOfCategoryIterator->second[finalSpecificationNewName] = suppressedOldSpec;
            }
        }

        auto specs = GetActiveSpecifications();
        emit SpecificationItemsChanged(specs);

        SwitchCurrentSpecificationTo(finalSpecificationNewName);
        CheckModifyState();
    }

    void EditingProjectComponentContext::CopySpecification(const std::wstring & sourceSpecificationName, const std::wstring & targetSpecificationName)
    {
        if (!m_spActiveComponent)
        {
            return;
        }

        auto finalTargetSpecificationName = QString::fromStdWString(targetSpecificationName).trimmed().toStdWString();
        if (finalTargetSpecificationName.empty())
        {
            return;
        }

        if (finalTargetSpecificationName == sourceSpecificationName)
        {
            return;
        }

        auto foundSourceSpecIterator = m_spActiveComponent->Specifications.find(sourceSpecificationName);
        if (foundSourceSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return;
        }

        auto foundTargetSpecIterator = m_spActiveComponent->Specifications.find(finalTargetSpecificationName);
        if (foundTargetSpecIterator != m_spActiveComponent->Specifications.end())
        {
            return;
        }

        auto sourceSpec = m_spActiveComponent->Specifications[sourceSpecificationName];
        if (!sourceSpec)
        {
            return;
        }

        if (m_state & ModifyState::Dirty)
        {
            auto result = Stage(sourceSpecificationName);
            if (!result)
            {
                return;
            }
        }

        auto clonedSpec = sourceSpec->CloneWithExternalParameterDefinition(m_spActiveComponent->ParameterDefinitions);
        DBG_WARN_AND_RETURN_VOID_UNLESS(clonedSpec != nullptr, L"clonedSpec为空", L"GMEP", L"2024-01-30");
        clonedSpec->Name = finalTargetSpecificationName;
        clonedSpec->TypeId = NewTypeGuid(); // 新增族类型应使用新id
        m_spActiveComponent->Specifications[finalTargetSpecificationName] = clonedSpec;

        // copy the spec in suppressed bin
        auto foundParamBinOfCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundParamBinOfCategoryIterator != m_customParametersBinByCategory.end())
        {
            auto foundParamBinOfSpecIterator = foundParamBinOfCategoryIterator->second.find(sourceSpecificationName);
            if (foundParamBinOfSpecIterator != foundParamBinOfCategoryIterator->second.end())
            {
                auto suppressedSourceSpec = foundParamBinOfCategoryIterator->second[sourceSpecificationName];
                if (suppressedSourceSpec)
                {
                    auto externalDefinitions = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
                    auto foundParamDefBinOfCategoryIterator = m_customParameterDefinitionsBinByCategory.find(m_spActiveComponent->CategoryCode);
                    if (foundParamDefBinOfCategoryIterator != m_customParameterDefinitionsBinByCategory.end())
                    {
                        auto &foundParamDefBinOfCategory = foundParamDefBinOfCategoryIterator->second;
                        for (auto & foundParamDefPair : foundParamDefBinOfCategory)
                        {
                            auto foundParamDef = foundParamDefPair.second;
                            if (foundParamDef)
                            {
                                externalDefinitions[foundParamDef->GetName()] = foundParamDef;
                            }
                        }
                    }

                    auto clonedSpec = suppressedSourceSpec->CloneWithExternalParameterDefinition(externalDefinitions);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(clonedSpec != nullptr, L"clonedSpec为空", L"GMEP", L"2024-01-30");
                    clonedSpec->Name = finalTargetSpecificationName;
                    clonedSpec->TypeId = NewTypeGuid();

                    foundParamBinOfCategoryIterator->second[finalTargetSpecificationName] = clonedSpec;
                }
            }
        }

        auto specs = GetActiveSpecifications();
        emit SpecificationItemsChanged(specs);

        SwitchCurrentSpecificationTo(finalTargetSpecificationName);
        CheckModifyState();
    }

    bool EditingProjectComponentContext::ModifyParameterName(const std::wstring parameterOldName, const std::wstring parameterNewName, std::wstring &errorMessage)
    {
        auto finalParameterNewName = QString::fromStdWString(parameterNewName).trimmed().toStdWString();
        if (finalParameterNewName.empty())
        {
            errorMessage = QString::fromStdWString(GBMP_TR(L"参数名不能为空白")).toStdWString();
            return false;
        }

        if (finalParameterNewName == parameterOldName)
        {
            return false;
        }

        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundOldParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(parameterOldName);
        if (foundOldParamDefIterator == m_spActiveComponent->ParameterDefinitions.end())
        {
            return false;
        }

        if (foundOldParamDefIterator->second && !foundOldParamDefIterator->second->IsNameEditable())
        {
            return false;
        }

        auto foundNewParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(finalParameterNewName);
        if (foundNewParamDefIterator != m_spActiveComponent->ParameterDefinitions.end())
        {
            errorMessage = (QString::fromStdWString(GBMP_TR(L"参数名")) + QString::fromStdWString(GBMP_TR(L" ")) + QString::fromStdWString(finalParameterNewName) + QString::fromStdWString(GBMP_TR(L" ")) + QString::fromStdWString(GBMP_TR(L"已存在"))).toStdWString();
            return false;
        }

        auto foundCategoryPropertyIterator = m_mpCategoryProperties.find(m_spActiveComponent->CategoryCode);
        if (foundCategoryPropertyIterator != m_mpCategoryProperties.end())
        {
            auto foundCategoryProperty = foundCategoryPropertyIterator->second;
            if (foundCategoryProperty)
            {
                auto foundCategoryParamDefIterator = foundCategoryProperty->Properties.find(finalParameterNewName);
                if (foundCategoryParamDefIterator != foundCategoryProperty->Properties.end())
                {
                    errorMessage = (QString::fromStdWString(GBMP_TR(L"参数名")) + QString::fromStdWString(GBMP_TR(L" ")) + QString::fromStdWString(finalParameterNewName) + QString::fromStdWString(GBMP_TR(L" ")) + QString::fromStdWString(GBMP_TR(L"已存在于可选的标准参数中"))).toStdWString();
                    return false;
                }
            }
        }

        auto oldParamDef = m_spActiveComponent->ParameterDefinitions[parameterOldName];
        if (oldParamDef)
        {
            oldParamDef->SetName(finalParameterNewName);
        }
        m_spActiveComponent->ParameterDefinitions.erase(parameterOldName);
        m_spActiveComponent->ParameterDefinitions[finalParameterNewName] = oldParamDef;

        for (auto &specPair : m_spActiveComponent->Specifications)
        {
            auto spec = specPair.second;
            if (spec)
            {
                auto foundParamIterator = spec->Parameters.find(parameterOldName);
                if (foundParamIterator != spec->Parameters.end())
                {
                    auto oldParam = spec->Parameters[parameterOldName];
                    
                    if (oldParam && oldParam->Definition && oldParam->Definition->GetName() != finalParameterNewName)
                    {
                        oldParam->Definition->SetName(finalParameterNewName);
                    }

                    spec->Parameters.erase(parameterOldName);
                    spec->Parameters[finalParameterNewName] = oldParam;
                }
            }
        }

        CheckCanDesuppressParameters();

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::ModifyParameterValue(const std::wstring & specificationName, const std::wstring & parameterName, const std::wstring & parameterOldValue, const std::wstring & parameterNewValue)
    {
        auto finalParameterNewValue = QString::fromStdWString(parameterNewValue).trimmed().toStdWString();
        
        if (parameterOldValue == finalParameterNewValue)
        {
            return false;
        }

        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundSpecIterator = m_spActiveComponent->Specifications.find(specificationName);
        if (foundSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return false;
        }

        auto &spec = m_spActiveComponent->Specifications[specificationName];
        if (!spec)
        {
            return false;
        }

        auto foundParamIterator = spec->Parameters.find(parameterName);
        if (foundParamIterator == spec->Parameters.end())
        {
            return false;
        }

        auto &param = spec->Parameters[parameterName];
        if (!param)
        {
            return false;
        }

        if (!param->IsValueEditable())
        {
            return false;
        }

        if (param->Value == parameterNewValue)
        {
            return false;
        }

        param->Value = finalParameterNewValue;
        param->SetIsValueSpecified(true);

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::ModifyParameterUnit(const std::wstring & parameterName, const std::wstring & parameterOldUnit, const std::wstring & parameterNewUnit)
    {
        // not to do for now
        return false;
    }

    bool EditingProjectComponentContext::ModifyParameterIsInstance(const std::wstring & parameterName, const bool & parameterOldIsInstance, const bool & parameterNewIsInstance)
    {
        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(parameterName);
        if (foundParamDefIterator == m_spActiveComponent->ParameterDefinitions.end())
        {
            return false;
        }

        auto &paramDef = m_spActiveComponent->ParameterDefinitions[parameterName];
        if (!paramDef)
        {
            return false;
        }

        if (!paramDef->IsInstanceEditable())
        {
            return false;
        }

        if (paramDef->GetIsInstance() == parameterNewIsInstance)
        {
            return false;
        }

        paramDef->SetIsInstance(parameterNewIsInstance);

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::ModifyParameterUnit(const std::wstring& sCategoryCode, std::map<std::wstring, std::shared_ptr<IParameterDefinition>>& parameterDefinitions)
    {
        QJsonArray paramDefinitionsArr = ComponentCommonUtils::GetCategoryProperty(sCategoryCode);

        for (auto& item : parameterDefinitions)
        {
            if(nullptr == item.second)
                continue;

            for (int i = 0; i < paramDefinitionsArr.size(); i++)
            {
                QJsonValue value = paramDefinitionsArr.at(i);
                QJsonObject obj = value.toObject();
                
                if (item.second->GetCode() == obj["code"].toString().toStdWString())
                {
                    std::wstring unit = obj["unit"].toString().toStdWString();
                    std::wstring unitCode = obj["unitCode"].toString().toStdWString();

                    if ((int)unit.size() > 0)
                    {
                        item.second->SetUnitSymbol(unit);
                    }
                    if ((int)unitCode.size() > 0)
                    {
                        item.second->SetUnitCode(unitCode);
                    }
                    break;
                }
            }
        }
        
        return true;
    }

    bool EditingProjectComponentContext::AddParameterDefinitions(const std::map<std::wstring, std::shared_ptr<IParameterDefinition>>& paramterDefintionsToBeAdded)
    {
        if (paramterDefintionsToBeAdded.empty())
        {
            return false;
        }

        if (!m_spActiveComponent)
        {
            return false;
        }

        auto parameterDefinitionsCanBeAdded = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
        auto parameterDefinitionsWillBeSuppressed = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();

        for (auto &toBeAddedParamDefPair : paramterDefintionsToBeAdded)
        {
            auto toBeAddedParamDef = toBeAddedParamDefPair.second;
            if (toBeAddedParamDef)
            {
                auto conflictParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(toBeAddedParamDef->GetName());
                if (conflictParamDefIterator == m_spActiveComponent->ParameterDefinitions.end())
                {
                    parameterDefinitionsCanBeAdded[toBeAddedParamDef->GetName()] = toBeAddedParamDef;
                    continue;
                }

                auto conflictParamDef = conflictParamDefIterator->second;
                if (conflictParamDef)
                {
                    if (toBeAddedParamDef->GetIsBuiltIn() || toBeAddedParamDef->IsGeometry() || toBeAddedParamDef->GetIsDrivingParameter() || toBeAddedParamDef->GetIsOutputParameter())
                    {
                        // do not consider for now
                        continue;
                    }
                    else if (toBeAddedParamDef->GetIsStandard() && !toBeAddedParamDef->GetIsEssential())
                    {
                        if (conflictParamDef->GetIsBuiltIn() || conflictParamDef->IsGeometry() || conflictParamDef->GetIsDrivingParameter() || conflictParamDef->GetIsOutputParameter())
                        {
                            continue;
                        }
                        else if (conflictParamDef->GetIsStandard())
                        {
                            continue;
                        }
                        else
                        {
                            parameterDefinitionsCanBeAdded[toBeAddedParamDef->GetName()] = toBeAddedParamDef;
                            parameterDefinitionsWillBeSuppressed[conflictParamDef->GetName()] = conflictParamDef;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }

        if (parameterDefinitionsCanBeAdded.empty())
        {
            return false;
        }

        if (!parameterDefinitionsWillBeSuppressed.empty())
        {
            auto paramNames = std::vector<std::wstring>();
            for (auto &willBeSuppressedParamDefPair : parameterDefinitionsWillBeSuppressed)
            {
                auto willBeSuppressedParamDef = willBeSuppressedParamDefPair.second;
                if (willBeSuppressedParamDef)
                {
                    paramNames.push_back(willBeSuppressedParamDef->GetName());
                }
            }
            SuppressParameters(paramNames);
        }

        for (auto &canBeAddedParamDefPair : parameterDefinitionsCanBeAdded)
        {
            auto canBeAddedParamDef = canBeAddedParamDefPair.second;
            if (canBeAddedParamDef)
            {
                m_spActiveComponent->ParameterDefinitions[canBeAddedParamDef->GetName()] = canBeAddedParamDef;

                for (auto &specPair : m_spActiveComponent->Specifications)
                {
                    auto spec = specPair.second;
                    if (spec)
                    {
                        auto newParameter = std::make_shared<IParameter>();
                        DBG_WARN_AND_CONTINUE_UNLESS(newParameter != nullptr, L"newParameter为空", L"GMEP", L"2024-01-30");
                        newParameter->Definition = canBeAddedParamDef;
                        spec->Parameters[canBeAddedParamDef->GetName()] = newParameter;
                    }
                }
            }
        }

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::RemoveParameterDefinitions(const std::map<std::wstring, std::shared_ptr<IParameterDefinition>>& paramterDefintionsToBeRemoved)
    {
        if (paramterDefintionsToBeRemoved.empty())
        {
            return false;
        }

        if (!m_spActiveComponent)
        {
            return false;
        }

        for (auto &toBeRemovedParamDefPair : paramterDefintionsToBeRemoved)
        {
            auto toBeRemovedParamName = toBeRemovedParamDefPair.first;
            auto foundParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(toBeRemovedParamName);
            if (foundParamDefIterator != m_spActiveComponent->ParameterDefinitions.end())
            {
                m_spActiveComponent->ParameterDefinitions.erase(toBeRemovedParamName);
            }

            for (auto &specPair : m_spActiveComponent->Specifications)
            {
                auto spec = specPair.second;
                if (spec)
                {
                    auto foundParamIterator = spec->Parameters.find(toBeRemovedParamName);
                    if (foundParamIterator != spec->Parameters.end())
                    {
                        spec->Parameters.erase(toBeRemovedParamName);
                    }
                }
            }
        }

        CheckCanDesuppressParameters();

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::ModifyLegend(const ILegend::LegendType & legendType, const std::shared_ptr<ILegend>& oldLegend, const std::shared_ptr<ILegend>& newLegend)
    {
        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundLegendIterator = m_spActiveComponent->Legends.find(legendType);
        if (foundLegendIterator == m_spActiveComponent->Legends.end())
        {
            m_spActiveComponent->Legends[legendType] = nullptr;
        }

        auto &foundLegend = m_spActiveComponent->Legends[legendType];
        if (foundLegend == nullptr && newLegend == nullptr)
        {
            return false;
        }

        if (foundLegend != nullptr && newLegend != nullptr && (*(foundLegend) == *(newLegend)))
        {
            return false;
        }
        
        m_spActiveComponent->Legends[legendType] = newLegend;

        CheckModifyState();

        return true;
    }

    bool EditingProjectComponentContext::UpdateDrivenParameters(const std::wstring & spec, std::wstring & errorMessage, bool bNeedUpdate)
    {
        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundSpecIterator = m_spActiveComponent->Specifications.find(spec);
        if (foundSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return false;
        }

        auto foundSpec = foundSpecIterator->second;
        if (!foundSpec)
        {
            return false;
        }

        if (!m_spFamilyFileService)
        {
            m_spFamilyFileService = FamilyFileService::Create(m_componentLocalFilePath);
        }

        if (!m_spFamilyFileService)
        {
            return false;
        }

        bool hasUpdated = false;
        auto result = m_spFamilyFileService->UpdateDrivenParameters(foundSpec, hasUpdated);

        if (bNeedUpdate)
        {
            emit DrivenParameterUpdateFinish(result, hasUpdated);
        }        

        return result;
    }

    bool EditingProjectComponentContext::UpdateGeometry(const std::wstring & spec, std::wstring & errorMessage, bool bNeedUpdate)
    {
        if (!m_spActiveComponent)
        {
            return false;
        }

        auto foundSpecIterator = m_spActiveComponent->Specifications.find(spec);
        if (foundSpecIterator == m_spActiveComponent->Specifications.end())
        {
            return false;
        }

        auto foundSpec = foundSpecIterator->second;
        if (!foundSpec)
        {
            return false;
        }

        if (!m_spFamilyFileService)
        {
            m_spFamilyFileService = FamilyFileService::Create(m_componentLocalFilePath);
        }

        if (!m_spFamilyFileService)
        {
            return false;
        }

        auto result = m_spFamilyFileService->TryUpdateGeometry(foundSpec);

        if (bNeedUpdate)
        {
            emit GeometryUpdateFinish(result);
        }        

        return result;
    }

    int EditingProjectComponentContext::GetModifyState()
    {
        return m_state;
    }

    void EditingProjectComponentContext::CheckCanDesuppressParameters()
    {
        if (!m_spActiveComponent)
        {
            return;
        }

        auto foundParamDefBinOfCategoryIterator = m_customParameterDefinitionsBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundParamDefBinOfCategoryIterator == m_customParameterDefinitionsBinByCategory.end())
        {
            return;
        }
        auto &foundParamDefBinOfCategory = m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode];
        if (foundParamDefBinOfCategory.empty())
        {
            return;
        }

        std::map<std::wstring, std::shared_ptr<IParameterDefinition>> parameterDefinitionsToBeDesuppressed;
        for (auto &suppressedParamDefPair : foundParamDefBinOfCategory)
        {
            auto suppressedParamDef = suppressedParamDefPair.second;
            if (suppressedParamDef)
            {
                auto foundActiveParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(suppressedParamDef->GetName());
                if (foundActiveParamDefIterator == m_spActiveComponent->ParameterDefinitions.end())
                {
                    parameterDefinitionsToBeDesuppressed[suppressedParamDef->GetName()] = suppressedParamDef;
                }
            }
        }

        if (parameterDefinitionsToBeDesuppressed.empty())
        {
            return;
        }

        auto foundParamBinOfCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundParamBinOfCategoryIterator == m_customParametersBinByCategory.end())
        {
            m_customParametersBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<ISpecification>>();
        }
        auto &foundParamBinOfCategory = m_customParametersBinByCategory[m_spActiveComponent->CategoryCode];

        std::vector<std::wstring> finalDesuppressedParamNames;

        for (auto &paramDefToBeDesuppressedPair : parameterDefinitionsToBeDesuppressed)
        {
            auto paramDefToBeDesuppressed = paramDefToBeDesuppressedPair.second;
            if (paramDefToBeDesuppressed)
            {
                foundParamDefBinOfCategory.erase(paramDefToBeDesuppressed->GetName());
                m_spActiveComponent->ParameterDefinitions[paramDefToBeDesuppressed->GetName()] = paramDefToBeDesuppressed;

                for (auto &specPair : m_spActiveComponent->Specifications)
                {
                    auto spec = specPair.second;
                    if (spec)
                    {
                        auto desuppressParameter = std::make_shared<IParameter>();
                        DBG_WARN_AND_CONTINUE_UNLESS(desuppressParameter != nullptr, L"desuppressParameter为空", L"GMEP", L"2024-01-30");
                        desuppressParameter->Definition = paramDefToBeDesuppressed;

                        auto foundParamBinOfSpecIterator = foundParamBinOfCategory.find(spec->Name);
                        if (foundParamBinOfSpecIterator != foundParamBinOfCategory.end())
                        {
                            auto foundParamBinOfSpec = foundParamBinOfSpecIterator->second;
                            if (foundParamBinOfSpec)
                            {
                                auto foundParamInBinIterator = foundParamBinOfSpec->Parameters.find(paramDefToBeDesuppressed->GetName());
                                if (foundParamInBinIterator != foundParamBinOfSpec->Parameters.end())
                                {
                                    auto foundParamInBin = foundParamInBinIterator->second;
                                    if (foundParamInBin)
                                    {
                                        desuppressParameter->Value = foundParamInBin->Value;
                                        desuppressParameter->SetIsValueSpecified(foundParamInBin->IsValueSpecified());
                                    }

                                    foundParamBinOfSpec->Parameters.erase(paramDefToBeDesuppressed->GetName());
                                }
                            }
                        }

                        spec->Parameters[desuppressParameter->Definition->GetName()] = desuppressParameter;
                    }
                }

                finalDesuppressedParamNames.push_back(paramDefToBeDesuppressed->GetName());
            }            
        }

        if (!finalDesuppressedParamNames.empty())
        {
            emit SuppressedParametersChanged({}, finalDesuppressedParamNames);
        }
    }

    void EditingProjectComponentContext::SuppressParameters(const std::vector<std::wstring>& parameterNames)
    {
        if (parameterNames.empty())
        {
            return;
        }

        if (!m_spActiveComponent)
        {
            return;
        }

        auto suppressed = std::vector<std::wstring>();

        auto foundSuppressedParamDefBinIterator = m_customParameterDefinitionsBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundSuppressedParamDefBinIterator == m_customParameterDefinitionsBinByCategory.end())
        {
            m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
        }
        auto &suppressedParamDefBin = m_customParameterDefinitionsBinByCategory[m_spActiveComponent->CategoryCode];

        auto foundSuppressedParamBinOfCategoryIterator = m_customParametersBinByCategory.find(m_spActiveComponent->CategoryCode);
        if (foundSuppressedParamBinOfCategoryIterator == m_customParametersBinByCategory.end())
        {
            m_customParametersBinByCategory[m_spActiveComponent->CategoryCode] = std::map<std::wstring, std::shared_ptr<ISpecification>>();
        }
        auto &suppressedParamBinsOfCategory = m_customParametersBinByCategory[m_spActiveComponent->CategoryCode];
                
        for (auto &toBeSuppressedParamName : parameterNames)
        {
            auto foundParamDefIterator = m_spActiveComponent->ParameterDefinitions.find(toBeSuppressedParamName);
            if (foundParamDefIterator != m_spActiveComponent->ParameterDefinitions.end())
            {
                auto foundParamDef = foundParamDefIterator->second;
                if (foundParamDef)
                {
                    suppressedParamDefBin[foundParamDef->GetName()] = foundParamDef;
                    m_spActiveComponent->ParameterDefinitions.erase(foundParamDef->GetName());
                }
            }

            for (auto &specPair : m_spActiveComponent->Specifications)
            {
                auto spec = specPair.second;
                if (spec)
                {
                    auto foundParamIterator = spec->Parameters.find(toBeSuppressedParamName);
                    if (foundParamIterator != spec->Parameters.end())
                    {
                        auto fondParam = foundParamIterator->second;
                        if (fondParam)
                        {
                            auto foundSuppressedParamBinOfSpecIterator = suppressedParamBinsOfCategory.find(m_currentSpecificationName);
                            if (foundSuppressedParamBinOfSpecIterator == suppressedParamBinsOfCategory.end())
                            {
                                auto spec = std::make_shared<ISpecification>();
                                DBG_WARN_AND_CONTINUE_UNLESS(spec != nullptr, L"spec为空", L"GMEP", L"2024-01-30");
                                spec->Name = m_currentSpecificationName;
                                suppressedParamBinsOfCategory[m_currentSpecificationName] = spec;
                            }
                            auto &suppressedParamBinOfSpec = suppressedParamBinsOfCategory[m_currentSpecificationName];

                            DBG_WARN_AND_CONTINUE_UNLESS(suppressedParamBinOfSpec != nullptr, L"suppressedParamBinOfSpec为空", L"GMEP", L"2024-01-30");
                            suppressedParamBinOfSpec->Parameters[toBeSuppressedParamName] = fondParam;
                            spec->Parameters.erase(toBeSuppressedParamName);
                        
                            suppressed.push_back(toBeSuppressedParamName);
                        }
                    }
                }
            }
        }

        if (!suppressed.empty())
        {
            emit SuppressedParametersChanged(suppressed, {});
        }
    }

    std::vector<std::shared_ptr<IGmepGcsCategory>> EditingProjectComponentContext::GetFullCategories(std::wstring leafCategoryCode) const
    {
        if (m_vCategories.empty() || leafCategoryCode.empty())
        {
            return std::vector<std::shared_ptr<IGmepGcsCategory>>();
        }

        std::shared_ptr<IGmepGcsCategory> spLeafCategory = nullptr;
        for (auto category : m_vCategories)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(category != nullptr, L"category为空", L"GMEP", L"2024-01-30");
            if (category->Code == leafCategoryCode)
            {
                spLeafCategory = category;
                break;
            }
        }

        if (!spLeafCategory)
        {
            return std::vector<std::shared_ptr<IGmepGcsCategory>>();
        }

        std::shared_ptr<IGmepGcsCategory> spParentCategory = nullptr;
        for (auto category : m_vCategories)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(category != nullptr, L"category为空", L"GMEP", L"2024-01-30");
            if (category->Code == spLeafCategory->ParentCode)
            {
                spParentCategory = category;
                break;
            }
        }

        if (!spParentCategory || spParentCategory->Code.empty() || spParentCategory->Code == L"0")
        {
            return{ spLeafCategory };
        }

        auto categories = GetFullCategories(spParentCategory->Code);
        categories.push_back(spLeafCategory);
        return categories;
    }

    std::wstring EditingProjectComponentContext::NewTypeGuid()
    {
        gcmp::UniIdentity guid = gcmp::GuidUtils::Generate();
        return gcmp::GuidUtils::ToString(guid.GetGuid(), false, false);
    }

}
